home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 14 / CU Amiga Magazine's Super CD-ROM 14 (1997)(EMAP Images)(GB)(Track 1 of 3)[!][issue 1997-09].iso / CUCD / Sound / GSMToast / src / toast.c < prev   
Encoding:
C/C++ Source or Header  |  1997-03-09  |  18.0 KB  |  817 lines

  1. /*
  2.  * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische
  3.  * Universitaet Berlin.  See the accompanying file "COPYRIGHT" for
  4.  * details.  THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE.
  5.  */
  6.  
  7. /* $Header: /tmp_amd/presto/export/kbs/jutta/src/gsm/RCS/toast.c,v 1.8 1996/07/02 10:41:04 jutta Exp $ */
  8.  
  9. #include        "toast.h"
  10.  
  11. /*  toast -- lossy sound compression using the gsm library.
  12.  */
  13.  
  14. char   * progname;
  15.  
  16. int     f_decode   = 0;         /* decode rather than encode     (-d) */
  17. int     f_cat      = 0;         /* write to stdout; implies -p   (-c) */
  18. int     f_force    = 0;         /* don't ask about replacements  (-f) */
  19. int     f_precious = 0;         /* avoid deletion of original    (-p) */
  20. int     f_fast     = 0;         /* use faster fpt algorithm      (-F) */
  21. int     f_verbose  = 0;         /* debugging                     (-V) */
  22. int     f_ltp_cut  = 0;         /* LTP cut-off margin            (-C) */
  23.  
  24. #ifdef AMIGA
  25.     int amigalinear=0;
  26. #endif
  27.  
  28. struct stat instat;             /* stat (inname)                 */
  29.  
  30. FILE    *in,     *out;
  31. char    *inname, *outname;
  32.  
  33. /*
  34.  *  The function (*output)() writes a frame of 160 samples given as
  35.  *  160 signed 16 bit values (gsm_signals) to <out>.
  36.  *  The function (*input)() reads one such frame from <in>.
  37.  *  The function (*init_output)() begins output (e.g. writes a header).,
  38.  *  The function (*init_input)() begins input (e.g. skips a header).
  39.  *
  40.  *  There are different versions of input, output, init_input and init_output
  41.  *  for different formats understood by toast; which ones are used 
  42.  *  depends on the command line arguments and, in their absence, the
  43.  *  filename; the fallback is #defined in toast.h
  44.  *
  45.  *  The specific implementations of input, output, init_input and init_output
  46.  *  for a format `foo' live in toast_foo.c.
  47.  */
  48.  
  49. int     (*output   ) P((gsm_signal *)),
  50.     (*input    ) P((gsm_signal *));
  51. int     (*init_input)  P((void)),
  52.     (*init_output) P((void));
  53.  
  54. static int      generic_init P0() { return 0; } /* NOP */
  55.  
  56. struct fmtdesc {
  57.  
  58.     char * name, * longname, * suffix;
  59.  
  60.     int  (* init_input )  P((void)),
  61.          (* init_output)  P((void));
  62.  
  63.     int  (* input ) P((gsm_signal * )),
  64.          (* output) P((gsm_signal * ));
  65.  
  66. } f_audio = {
  67.         "audio",
  68.         "8 kHz, 8 bit u-law encoding with Sun audio header", ".au",
  69.         audio_init_input,
  70.         audio_init_output,
  71.         ulaw_input,
  72.         ulaw_output
  73. }, f_ulaw = {
  74.         "u-law", "plain 8 kHz, 8 bit u-law encoding", ".u",
  75.         generic_init,
  76.         generic_init,
  77.         ulaw_input,
  78.         ulaw_output 
  79.  
  80. }, f_alaw = {
  81.         "A-law", "8 kHz, 8 bit A-law encoding", ".A",
  82.         generic_init,
  83.         generic_init,
  84.         alaw_input,
  85.         alaw_output
  86.  
  87. }, f_linear = {
  88.         "linear",
  89.         "16 bit (13 significant) signed 8 kHz signal", ".l",
  90.         generic_init,
  91.         generic_init,
  92.         linear_input,
  93.         linear_output
  94. };
  95.  
  96. struct fmtdesc * alldescs[] = {
  97.     &f_audio,
  98.     &f_alaw,
  99.     &f_ulaw,
  100.     &f_linear,
  101.     (struct fmtdesc *)NULL
  102. };
  103.  
  104. #define DEFAULT_FORMAT  f_ulaw          /* default audio format, others */
  105.                     /* are: f_alaw,f_audio,f_linear */
  106. struct fmtdesc * f_format  = 0;
  107.  
  108. /*
  109.  *  basename + suffix of a pathname
  110.  */
  111. static char * endname P1((name), char * name)
  112. {
  113.     if (name) {
  114.         char * s = strrchr(name, '/');
  115.         if (s && s[1]) name = s + 1;
  116.     }
  117.     return name;
  118.  
  119. }
  120.  
  121. /*
  122.  *  Try to figure out what we're supposed to do from the argv[0], if
  123.  *  any, and set the parameters accordingly.
  124.  */
  125. static void parse_argv0 P1((av0), char * av0 )
  126. {
  127.     int     l;
  128.  
  129.     progname = av0 = endname(av0 ? av0 : "toast");
  130.  
  131.     /*  If the name starts with `un', we want to decode, not code.
  132.      *  If the name ends in `cat', we want to write to stdout,
  133.      *  and decode as well.
  134.      */
  135.  
  136.     if (!strncmp(av0, "un", 2)) f_decode = 1;
  137.     if (  (l = strlen(av0)) >= 3 /* strlen("cat") */
  138.        && !strcmp( av0 + l - 3, "cat" )) f_cat = f_decode = 1;
  139. }
  140.  
  141.  
  142. /*
  143.  *  Check whether the name (possibly generated by appending
  144.  *  .gsm to something else) is short enough for this system.
  145.  */
  146. static int length_okay P1((name), char * name)
  147. {
  148.     long    max_filename_length = 0;
  149.     char    * end;
  150.  
  151.     /* If our _pathname_ is too long, we'll usually not be
  152.      * able to open the file at all -- don't worry about that.
  153.      * 
  154.      * But if the _filename_ is too long, there is danger of
  155.      * silent truncation on some systems, which results
  156.      * in the target replacing the source!
  157.      */
  158.  
  159.     if (!name) return 0;
  160.     end = endname(name);
  161.  
  162. #ifdef  NAME_MAX
  163.     max_filename_length  = NAME_MAX;
  164. #else
  165. #ifdef  _PC_NAME_MAX
  166. #ifdef USE_PATHCONF
  167.     {       char * s, tmp; 
  168.         
  169.         /*  s = dirname(name)
  170.          */
  171.         if ((s = end) > name) {
  172.             if (s > name + 1) s--;
  173.             tmp = s;
  174.             *s  = 0;
  175.         }
  176.  
  177.         errno = 0;
  178.         max_filename_length = pathconf(s > name ? name : ".",
  179.             _PC_NAME_MAX);
  180.         if (max_filename_length == -1 && errno) {
  181.             perror( s > name ? name : "." );
  182.             fprintf(stderr,
  183.         "%s: cannot get dynamic filename length limit for %s.\n",
  184.                 progname, s > name ? name : ".");
  185.             return 0;
  186.         }
  187.         if (s > name) *s = tmp;
  188.     }
  189. #endif /* USE_PATHCONF  */
  190. #endif /* _PC_NAME_MAX  */
  191. #endif /* !NAME_MAX     */
  192.  
  193.     if (max_filename_length > 0 && strlen(end) > max_filename_length) {
  194.         fprintf(stderr,
  195.             "%s: filename \"%s\" is too long (maximum is %ld)\n",
  196.             progname, endname(name), max_filename_length );
  197.         return 0;
  198.     }
  199.  
  200.     return 1;
  201. }
  202.  
  203. /*
  204.  *  Return a pointer the suffix of a string, if any.
  205.  *  A suffix alone has no suffix, an empty suffix can not be had.
  206.  */
  207. static char * suffix P2((name, suf), char *name, char * suf) 
  208. {
  209.     size_t nlen = strlen(name);
  210.     size_t slen = strlen(suf);
  211.  
  212.     if (!slen || nlen <= slen) return (char *)0;
  213.     name += nlen - slen;
  214.     return memcmp(name, suf, slen) ? (char *)0 : name;
  215. }
  216.  
  217.  
  218. static void catch_signals P1((fun), SIGHANDLER_T (*fun) ()) 
  219. {
  220. #ifdef  SIGHUP
  221.     signal( SIGHUP,   fun );
  222. #endif
  223. #ifdef  SIGINT
  224.     signal( SIGINT,   fun );
  225. #endif
  226. #ifdef  SIGPIPE
  227.     signal( SIGPIPE,  fun );
  228. #endif
  229. #ifdef  SIGTERM
  230.     signal( SIGTERM,  fun );
  231. #endif
  232. #ifdef  SIGXFSZ
  233.     signal( SIGXFSZ,  fun );
  234. #endif
  235. }
  236.  
  237. static SIGHANDLER_T onintr P0()
  238. {
  239.     char * tmp = outname;
  240.  
  241. #ifdef  HAS_SYSV_SIGNALS
  242.     catch_signals( SIG_IGN );
  243. #endif
  244.  
  245.     outname = (char *)0;
  246.     if (tmp) (void)unlink(tmp);
  247.  
  248.     exit(1);
  249. }
  250.  
  251. /*
  252.  *  Allocate some memory and complain if it fails.
  253.  */
  254. static char * emalloc P1((len), size_t len)
  255. {
  256.     char * s;
  257.     if (!(s = malloc(len))) {
  258.         fprintf(stderr, "%s: failed to malloc %d bytes -- abort\n",
  259.             progname, len);
  260.         onintr();
  261.         exit(1);
  262.     }
  263.     return s;
  264. }
  265.  
  266. static char* normalname P3((name, want, cut), char *name, char *want,char *cut)
  267. {
  268.     size_t  maxlen;
  269.     char    * s, * p;
  270.  
  271.     p = (char *)0;
  272.     if (!name) return p;
  273.  
  274.     maxlen = strlen(name) + 1 + strlen(want) + strlen(cut);
  275.     p = strcpy(emalloc(maxlen), name);
  276.  
  277.     if (s = suffix(p, cut)) strcpy(s, want);
  278.     else if (*want && !suffix(p, want)) strcat(p, want);
  279.  
  280.     return p;
  281. }
  282.  
  283. /*
  284.  *  Generate a `plain' (non-encoded) name from a given name.
  285.  */
  286. static char * plainname P1((name), char *name)
  287. {
  288.     return normalname(name, "", SUFFIX_TOASTED );
  289. }
  290.  
  291. /*
  292.  *  Generate a `code' name from a given name.
  293.  */
  294. static char * codename P1((name), char *name)
  295. {
  296.     return normalname( name, SUFFIX_TOASTED, "" );
  297. }
  298.  
  299. /*
  300.  *  If we're supposed to ask (fileno (stderr) is a tty, and f_force not
  301.  *  set), ask the user whether to overwrite a file or not.
  302.  */
  303. static int ok_to_replace P1(( name ), char * name)
  304. {
  305.     int reply, c;
  306.  
  307.     if (f_force) return 1;                  /* YES, do replace   */
  308.     if (!isatty(fileno(stderr))) return 0;  /* NO, don't replace */
  309.  
  310.     fprintf(stderr,
  311.         "%s already exists; do you wish to overwrite %s (y or n)? ",
  312.         name, name);
  313.     fflush(stderr);
  314.  
  315.     for (c = reply = getchar(); c != '\n' && c != EOF; c = getchar()) ;
  316.     if (reply == 'y') return 1;
  317.  
  318.     fprintf(stderr, "\tnot overwritten\n");
  319.     return 0;
  320. }
  321.  
  322. static void update_mode P0()
  323. {
  324.     if (!instat.st_nlink) return;           /* couldn't stat in */
  325.  
  326. #ifdef HAS_FCHMOD
  327.     if (fchmod(fileno(out), instat.st_mode & 07777)) {
  328.         perror(outname);
  329.         fprintf(stderr, "%s: could not change file mode of \"%s\"\n",
  330.             progname, outname);
  331.     }
  332. #else 
  333. #ifdef HAS_CHMOD
  334.     if (outname && chmod(outname, instat.st_mode & 07777)) {
  335.         perror(outname);
  336.         fprintf(stderr, "%s: could not change file mode of \"%s\"\n",
  337.             progname, outname);
  338.     }
  339. #endif /* HAS_CHMOD  */
  340. #endif /* HAS_FCHMOD */
  341. }
  342.  
  343. static void update_own P0()
  344. {
  345.     if (!instat.st_nlink) return; /* couldn't stat in */
  346. #ifdef HAS_FCHOWN
  347.     (void)fchown(fileno(out), instat.st_uid, instat.st_gid);
  348. #else 
  349. #ifdef HAS_CHOWN
  350.     (void)chown(outname, instat.st_uid, instat.st_gid);
  351. #endif /* HAS_CHOWN  */
  352. #endif /* HAS_FCHOWN */
  353. }
  354.  
  355. static void update_times P0()
  356. {
  357.     if (!instat.st_nlink) return;   /* couldn't stat in */
  358.  
  359. #ifdef HAS_UTIMES
  360.     if (outname) {
  361.         struct timeval tv[2];
  362.  
  363.         tv[0].tv_sec  = instat.st_atime;
  364.         tv[1].tv_sec  = instat.st_mtime;
  365.         tv[0].tv_usec = tv[1].tv_usec = 0;
  366.         (void) utimes(outname, tv);
  367.     }
  368. #else
  369. #ifdef HAS_UTIME
  370.  
  371.     if (outname) {
  372.  
  373. #ifdef  HAS_UTIMBUF
  374.         struct utimbuf ut;
  375.  
  376.         ut.actime     = instat.st_atime;
  377.         ut.modtime    = instat.st_mtime;
  378.  
  379. #       ifdef   HAS_UTIMEUSEC
  380.         ut.acusec     = instat.st_ausec;
  381.         ut.modusec    = instat.st_musec;
  382. #       endif   /* HAS_UTIMEUSEC */
  383.  
  384.         (void) utime(outname, &ut);
  385.  
  386. #else /* UTIMBUF */
  387.  
  388.         time_t ut[2];
  389.  
  390.         ut[0] = instat.st_atime;
  391.         ut[1] = instat.st_mtime;
  392.  
  393.         (void) utime(outname, ut);
  394.  
  395. #endif  /* UTIMBUF */
  396.     }
  397. #endif /* HAS_UTIME */
  398. #endif /* HAS_UTIMES */
  399. }
  400.  
  401.  
  402. static int okay_as_input P3((name,f,st), char* name, FILE* f, struct stat * st)
  403. {
  404. # ifdef HAS_FSTAT
  405.     if (fstat(fileno(f), st) < 0)
  406. # else
  407.     if (stat(name, st) < 0)
  408. # endif
  409.     {
  410.         perror(name);
  411.         fprintf(stderr, "%s: cannot stat \"%s\"\n", progname, name);
  412.         return 0;
  413.     }
  414.  
  415.     if (!S_ISREG(st->st_mode)) {
  416.         fprintf(stderr,
  417.             "%s: \"%s\" is not a regular file -- unchanged.\n",
  418.             progname, name);
  419.         return 0;
  420.     }
  421.     if (st->st_nlink > 1 && !f_cat && !f_precious) {
  422.         fprintf(stderr, 
  423.               "%s: \"%s\" has %s other link%s -- unchanged.\n",
  424.             progname,name,st->st_nlink - 1,"s" + (st->st_nlink<=2));
  425.         return 0;
  426.     }
  427.     return 1;
  428. }
  429.  
  430. static void prepare_io P1(( desc), struct fmtdesc * desc)
  431. {
  432.     output      = desc->output;
  433.     input       = desc->input;
  434.  
  435.     init_input  = desc->init_input;
  436.     init_output = desc->init_output;
  437. }
  438.  
  439. static struct fmtdesc * grok_format P1((name), char * name)
  440. {
  441.     char * c;
  442.     struct fmtdesc ** f;
  443.  
  444.     if (name) {
  445.         c = plainname(name);
  446.  
  447.         for (f = alldescs; *f; f++) {
  448.             if (  (*f)->suffix
  449.                && *(*f)->suffix
  450.                && suffix(c, (*f)->suffix)) {
  451.  
  452.                 free(c);
  453.                 return *f;
  454.             }
  455.         }
  456.  
  457.         free(c);
  458.     }
  459.     return (struct fmtdesc *)0;
  460. }
  461.  
  462. static int open_input P2((name, st), char * name, struct stat * st)
  463. {
  464.     struct fmtdesc * f = f_format;
  465.  
  466.     st->st_nlink = 0;       /* indicates `undefined' value */
  467.     if (!name) {
  468.         inname = (char *)NULL;
  469.         in     = stdin;
  470. #ifdef  HAS__FSETMODE
  471.         _fsetmode(in, "b");
  472. #endif
  473.     }
  474.     else {
  475.         if (f_decode) inname = codename(name);
  476.         else {
  477.             if (!f_cat && suffix(name, SUFFIX_TOASTED)) {
  478.                 fprintf(stderr,
  479.             "%s: %s already has \"%s\" suffix -- unchanged.\n",
  480.                     progname, name, SUFFIX_TOASTED );
  481.                 return 0;
  482.             }
  483.             inname = strcpy(emalloc(strlen(name)+1), name);
  484.         }
  485.         if (!(in = fopen(inname, READ))) {
  486.             perror(inname); /* not guaranteed to be valid here */
  487.             fprintf(stderr, "%s: cannot open \"%s\" for reading\n",
  488.                 progname, inname);
  489.             return 0;
  490.         }
  491.         if (!okay_as_input(inname, in, st)) return 0;
  492.         if (!f) f = grok_format(inname);
  493.     }
  494.     prepare_io( f ? f : & DEFAULT_FORMAT );
  495.     return 1;
  496. }
  497.  
  498. static int open_output P1((name), char *name)
  499. {
  500.     if (!name || f_cat) {
  501.         out     = stdout;
  502.         outname = (char *)NULL;
  503. #ifdef  HAS__FSETMODE
  504.         _fsetmode(out, "b"); 
  505. #endif
  506.     }
  507.     else {
  508.         int outfd = -1;
  509.         char * o;
  510.  
  511.         o = (*(f_decode ? plainname : codename))(name);
  512.         if (!length_okay(o)) return 0;
  513.         if ((outfd = open(o, O_WRITE_EXCL, 0666)) >= 0)
  514.             out = fdopen(outfd, WRITE);
  515.         else if (errno != EEXIST) out = (FILE *)NULL;
  516.         else if (ok_to_replace(o)) out = fopen(o, WRITE);
  517.         else return 0;
  518.  
  519.         if (!out) {
  520.             perror(o);
  521.             fprintf(stderr,
  522.                 "%s: can't open \"%s\" for writing\n",
  523.                 progname, o);
  524.             if (outfd >= 0) (void)close(outfd);
  525.             return 0;
  526.         }
  527.  
  528.         outname = o;
  529.     }
  530.     return 1;
  531. }
  532.  
  533. static int process_encode P0()
  534. {
  535.     gsm             r;
  536.     gsm_signal      s[ 160 ];
  537.     gsm_frame       d;
  538.  
  539.     int             cc;
  540.  
  541.     if (!(r = gsm_create())) {
  542.         perror(progname);
  543.         return -1;
  544.     }
  545.     (void)gsm_option(r, GSM_OPT_FAST,       &f_fast);
  546.     (void)gsm_option(r, GSM_OPT_VERBOSE,    &f_verbose);
  547.     (void)gsm_option(r, GSM_OPT_LTP_CUT,    &f_ltp_cut);
  548.  
  549.     while ((cc = (*input)(s)) > 0) {
  550.         if (cc < sizeof(s) / sizeof(*s))
  551.             memset((char *)(s+cc), 0, sizeof(s)-(cc * sizeof(*s)));
  552.         gsm_encode(r, s, d);
  553.         if (fwrite((char *)d, sizeof(d), 1, out) != 1) {
  554.             perror(outname ? outname : "stdout");
  555.             fprintf(stderr, "%s: error writing to %s\n",
  556.                 progname, outname ? outname : "stdout");
  557.             gsm_destroy(r);
  558.             return -1;
  559.         }
  560.     }
  561.     if (cc < 0) {
  562.         perror(inname ? inname : "stdin");
  563.         fprintf(stderr, "%s: error reading from %s\n",
  564.             progname, inname ? inname : "stdin");
  565.         gsm_destroy(r);
  566.         return -1;
  567.     }
  568.     gsm_destroy(r);
  569.  
  570.     return 0;
  571. }
  572.  
  573. static int process_decode P0()
  574. {
  575.     gsm             r;
  576.     gsm_frame       s;
  577.     gsm_signal      d[ 160 ];
  578.  
  579.     int             cc;
  580.  
  581.     if (!(r = gsm_create())) {      /* malloc failed */
  582.         perror(progname);
  583.         return -1;
  584.     }
  585.     (void)gsm_option(r, GSM_OPT_FAST,    &f_fast);
  586.     (void)gsm_option(r, GSM_OPT_VERBOSE, &f_verbose);
  587.  
  588.     while ((cc = fread(s, 1, sizeof(s), in)) > 0) {
  589.  
  590.         if (cc != sizeof(s)) {
  591.             if (cc >= 0) fprintf(stderr,
  592.             "%s: incomplete frame (%d byte%s missing) from %s\n",
  593.                     progname, sizeof(s) - cc,
  594.                     "s" + (sizeof(s) - cc == 1),
  595.                     inname ? inname : "stdin" );
  596.             gsm_destroy(r);
  597.             errno = 0;
  598.             return -1;
  599.         }
  600.         if (gsm_decode(r, s, d)) {
  601.             fprintf(stderr, "%s: bad frame in %s\n", 
  602.                 progname, inname ? inname : "stdin");
  603.             gsm_destroy(r);
  604.             errno = 0;
  605.             return -1;
  606.         }
  607.  
  608.         if ((*output)(d) < 0) {
  609.             perror(outname);
  610.             fprintf(stderr, "%s: error writing to %s\n",
  611.                     progname, outname);
  612.             gsm_destroy(r);
  613.             return -1;
  614.         }
  615.     }
  616.  
  617.     if (cc < 0) {
  618.         perror(inname ? inname : "stdin" );
  619.         fprintf(stderr, "%s: error reading from %s\n", progname,
  620.             inname ? inname : "stdin");
  621.         gsm_destroy(r);
  622.         return -1;
  623.     }
  624.  
  625.     gsm_destroy(r);
  626.     return 0;
  627. }
  628.  
  629. static int process P1((name), char * name)
  630. {
  631.     int step = 0;
  632.  
  633.     out     = (FILE *)0;
  634.     in      = (FILE *)0;
  635.  
  636.     outname = (char *)0;
  637.     inname  = (char *)0;
  638.  
  639.     if (!open_input(name, &instat) || !open_output(name))
  640.         goto err;
  641.  
  642.     if ((*(f_decode ? init_output    : init_input))()) {
  643.         fprintf(stderr, "%s: error %s %s\n",
  644.             progname,
  645.             f_decode ? "writing header to" : "reading header from",
  646.             f_decode ? (outname ? outname : "stdout")
  647.                  : (inname ? inname : "stdin"));
  648.         goto err;
  649.     }
  650.  
  651.     if ((*(f_decode ? process_decode : process_encode))())
  652.         goto err;
  653.  
  654.     if (fflush(out) < 0 || ferror(out)) {
  655.         perror(outname ? outname : "stdout");
  656.         fprintf(stderr, "%s: error writing \"%s\"\n", progname,
  657.                 outname ? outname:"stdout");
  658.         goto err;
  659.     }
  660.  
  661.     if (out != stdout) {
  662.  
  663.         update_times();
  664.         update_mode ();
  665.         update_own  ();
  666.  
  667.         if (fclose(out) < 0) {
  668.             perror(outname);
  669.             fprintf(stderr, "%s: error writing \"%s\"\n",
  670.                 progname, outname);
  671.             goto err;
  672.         }
  673.         if (outname != name) free(outname);
  674.         outname = (char *)0;
  675.     }
  676.     out = (FILE *)0;
  677.     if (in  != stdin) {
  678.         (void)fclose(in), in = (FILE *)0;
  679.         if (!f_cat && !f_precious) {
  680.             if (unlink(inname) < 0) {
  681.                 perror(inname);
  682.                 fprintf(stderr,
  683.                     "%s: source \"%s\" not deleted.\n",
  684.                     progname, inname);
  685.             }
  686.             goto err;
  687.         }
  688.         if (inname != name) free(inname);
  689.         inname = (char *)0;
  690.     }
  691.     return 0;
  692.  
  693.     /*
  694.      *  Error handling and cleanup.
  695.      */
  696. err:
  697.     if (out && out != stdout) {
  698.         (void)fclose(out), out = (FILE *)0;
  699.         if (unlink(outname) < 0 && errno != ENOENT && errno != EINTR) {
  700.             perror(outname);
  701.             fprintf(stderr, "%s: could not unlink \"%s\"\n",
  702.                 progname, outname);
  703.         }
  704.     }
  705.     if (in && in != stdin) (void)fclose(in), in = (FILE *)0;
  706.  
  707.     if (inname  && inname  != name) free(inname);
  708.     if (outname && outname != name) free(outname);
  709.  
  710.     return -1;
  711. }
  712.  
  713. static void version P0()
  714. {
  715.     printf( "%s 1.0, version %s\n",
  716.         progname,
  717.         "$Id: toast.c,v 1.8 1996/07/02 10:41:04 jutta Exp $" );
  718. }
  719.  
  720. static void help P0()
  721. {
  722.     printf("Usage: %s [-fcpdhvaulsFC] [files...]\n", progname);
  723.     printf("\n");
  724.  
  725.     printf(" -f  force     Replace existing files without asking\n");
  726.     printf(" -c  cat       Write to stdout, do not remove source files\n");
  727.     printf(" -d  decode    Decode data (default is encode)\n");
  728.     printf(" -p  precious  Do not delete the source\n");
  729.     printf("\n");
  730.  
  731.     printf(" -u  u-law     Force 8 kHz/8 bit u-law in/output format\n");
  732.     printf(" -s  sun .au   Force Sun .au u-law in/output format\n");
  733.     printf(" -a  A-law     Force 8 kHz/8 bit A-law in/output format\n");
  734.     printf(" -l  linear    Force 16 bit linear in/output format\n");
  735. #ifdef AMIGA
  736.     printf(" -e  8bit lin  Force 8 bit linear output (amiga)\n");
  737. #endif
  738.     printf("\n");
  739.  
  740.     printf(" -F  fast      Sacrifice conformance to performance\n");
  741.     printf(" -C  cutoff    Ignore most samples during LTP\n");
  742.     printf(" -v  version   Show version information\n");
  743.     printf(" -h  help      Print this text\n");
  744.     printf("\n");
  745. }
  746.  
  747.  
  748. static void set_format P1((f), struct fmtdesc * f)
  749. {
  750.     if (f_format && f_format != f) {
  751.         fprintf( stderr,
  752.     "%s: only one of -[uals] is possible (%s -h for help)\n",
  753.             progname, progname);
  754.         exit(1);
  755.     }
  756.  
  757.     f_format = f;
  758. }
  759.  
  760. int main P2((ac, av), int ac, char **av)
  761. {
  762.     int             opt;
  763.     extern int      optind;
  764.     extern char     * optarg;
  765.  
  766.     parse_argv0(*av);
  767.  
  768. #ifdef AMIGA
  769.     while ((opt = getopt(ac, av, "fcdpvhuasleVFC:")) != EOF) switch (opt) {
  770. #else
  771.     while ((opt = getopt(ac, av, "fcdpvhuaslVFC:")) != EOF) switch (opt) {
  772. #endif
  773.     case 'd': f_decode   = 1; break;
  774.     case 'f': f_force    = 1; break;
  775.     case 'c': f_cat      = 1; break;
  776.     case 'p': f_precious = 1; break;
  777.     case 'F': f_fast     = 1; break;
  778.     case 'C': f_ltp_cut  = 100; break;
  779. #ifndef NDEBUG
  780.     case 'V': f_verbose  = 1; break;        /* undocumented */
  781. #endif
  782.  
  783.     case 'u': set_format( &f_ulaw   ); break;
  784.     case 'l': set_format( &f_linear ); break;
  785.     case 'a': set_format( &f_alaw   ); break;
  786.     case 's': set_format( &f_audio  ); break;
  787. #ifdef AMIGA
  788.     case 'e':  /* dodgy 8 bit linear output. piggy backed on alaw */
  789.         amigalinear=1;
  790.         break;
  791. #endif
  792.  
  793.  
  794.     case 'v': version(); exit(0);
  795.     case 'h': help();    exit(0);
  796.  
  797.     default: 
  798.     usage:
  799.         fprintf(stderr,
  800.     "Usage: %s [-fcpdhvuaslFC] [files...] (-h for help)\n",
  801.             progname);
  802.         exit(1);
  803.     }
  804.  
  805.     f_precious |= f_cat;
  806.  
  807.     av += optind;
  808.     ac -= optind;
  809.  
  810.     catch_signals(onintr);
  811.  
  812.     if (ac <= 0) process( (char *)0 );
  813.     else while (ac--) process( *av++ );
  814.  
  815.     exit(0);
  816. }
  817.